<?php

declare(strict_types=1);

namespace App\Amqp\Consumer;

use App\Enum\EnumType;
use App\Service\act\TaskService;
use App\Service\BaseService;
use App\Service\UserService;
use Hyperf\Amqp\Result;
use Hyperf\Amqp\Annotation\Consumer;
use Hyperf\Amqp\Message\ConsumerMessage;
use Hyperf\DbConnection\Db;
use Hyperf\Di\Annotation\Inject;
use PhpAmqpLib\Message\AMQPMessage;
use Hyperf\Amqp\Message\Type;
use Psr\Log\LoggerInterface;

#[Consumer(exchange: 'send.prize.obj', routingKey: 'send-prize-obj', queue: 'queue-send-prize-obj', name: "SendPrizeObjConsumer", nums: 2, enable: true)]
class SendPrizeObjConsumer extends ConsumerMessage
{
    #[Inject]
    protected LoggerInterface $logger;

    protected Type|string $type = Type::DIRECT; // Type::FANOUT

    public function consumeMessage($data, AMQPMessage $message): Result
    {
        try {
            // 发放奖品
            $Task = new TaskService();
            // 获取用户信息
            $Task->currUser = UserService::getUserInfo($data['uid']);

            // 设置发放奖品数据
            $Task->setSendPrizeData($data, time(), $data['reason'] ?? 37);

            Db::transaction(function () use ($Task) {
                // 保存发放奖品数据
                $Task->saveSendPrizeData([
                    'cash_water_multiple' => $data['cash_water_multiple'] ?? 1,
                    'bonus_water_multiple' => $data['bonus_water_multiple'] ?? 1
                ]);

                // 更新数据库奖项数量
                $this->updatePrizeObjNum();
            });

            return Result::ACK;
        } catch (\Throwable $e) {
            $this->logger->alert('SendPrizeObjConsumer.$data：' . var_export($data, true));
            $this->logger->error('SendPrizeObjConsumer.Exception：' . $e->getMessage() . $e->getTraceAsString());
            BaseService::setListCache('MQ_PRODUCER_SEND_PRIZE_OBJ_EXCEPTION_LIST', json_encode($data));
            return Result::DROP;
        }
    }

    /**
     * 更新奖项数量
     * @return void
     * @throws \Psr\Container\ContainerExceptionInterface
     * @throws \Psr\Container\NotFoundExceptionInterface
     * @throws \RedisException
     */
    public function updatePrizeObjNum(): void
    {
        // 读取缓存中的奖项数量
        $data = BaseService::getCache(EnumType::PRIZE_OBJ_NUM_CACHE);
        if (empty($data)) return;

        $sql = "UPDATE br_act_prize_obj SET pobj_num = CASE pobj_id ";
        foreach ($data as $k => $v) {
            $sql .= sprintf("WHEN %d THEN %d ", $k, $v);
        }

        $ids = implode(',', array_keys($data));
        $sql .= "END WHERE pobj_id IN ({$ids})";
        Db::update($sql);
    }
}

